package cn.zwx.goods.svc.rpc;

import cn.zwx.base.entity.ResponseEntity;
import cn.zwx.base.exception.BizWrapException;
import cn.zwx.base.utils.PageUtil;
import cn.zwx.base.utils.ValidationUtils;
import cn.zwx.goods.svc.constans.GoodsConstans;
import cn.zwx.goods.svc.domain.bo.AttrBO;
import cn.zwx.goods.svc.domain.entity.AttrEntity;
import cn.zwx.goods.svc.domain.entity.AttrValueEntity;
import cn.zwx.goods.svc.domain.enums.GoodsCodeEnum;
import cn.zwx.goods.svc.rpc.dto.AttrPageListDTO;
import cn.zwx.goods.svc.rpc.dto.DeleteAttrDTO;
import cn.zwx.goods.svc.rpc.dto.InsertAttrDTO;
import cn.zwx.goods.svc.rpc.dto.ModifyAttrDTO;
import cn.zwx.goods.svc.rpc.facade.DubboAttrService;
import cn.zwx.goods.svc.rpc.vo.AttrInfoVO;
import cn.zwx.goods.svc.rpc.vo.InsertAttrVO;
import cn.zwx.goods.svc.service.AttrService;
import cn.zwx.goods.svc.service.CategoryService;
import cn.zwx.goods.svc.warp.ExceptionWrap;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.apidocs.annotations.ApiDoc;
import org.apache.dubbo.apidocs.annotations.ApiModule;
import org.apache.dubbo.config.annotation.DubboService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author zhangwenxue
 */
@Service
@ApiModule(value = "属性相关接口", apiInterface = DubboAttrService.class)
@DubboService(version = "v1.0.0",interfaceClass = DubboAttrService.class,timeout = 8000)
public class DubboAttrServiceImpl implements DubboAttrService {

    public static final Logger logger = LoggerFactory.getLogger(DubboAttrServiceImpl.class);


    @Resource
    public AttrService attrService;

    @Resource
    private CategoryService categoryService;

    @Override
    @ApiDoc(value = "分页查询属性列表接口")
    public ResponseEntity<PageUtil<AttrInfoVO>> selectPageList(AttrPageListDTO dto) throws BizWrapException {
        // 1.验证参数
        ValidationUtils.getInstance().validate(dto);
        // 2.select count
        PageUtil<AttrInfoVO> returnPage = new PageUtil<>(dto.getPageNum(),dto.getPageSize(), GoodsConstans.INT_0,new ArrayList<>());
        LambdaQueryWrapper<AttrEntity> queryBrandWrapper = new LambdaQueryWrapper<>();
        queryBrandWrapper.like(StringUtils.isNotBlank(dto.getAttrName()),AttrEntity::getName,dto.getAttrName());
        queryBrandWrapper.orderByDesc(AttrEntity::getUpdateTime);
        queryBrandWrapper.orderByDesc(AttrEntity::getCreateTime);
        Integer selectCount = attrService.selectCount(queryBrandWrapper);
        if (selectCount.equals(GoodsConstans.INT_0)){
            logger.info("not select record,params:{}", JSON.toJSONString(dto));
            return ResponseEntity.success(returnPage);
        }
        // 3.查询数据
        // 3.1计算分页
        Integer startIndex = dto.getPageNum().equals(GoodsConstans.INT_1)?GoodsConstans.INT_0:
                Math.subtractExact(dto.getPageNum(),1) * dto.getPageSize();
        final AttrBO attrBO = new AttrBO();
        attrBO.setPageSize(dto.getPageSize());
        attrBO.setStartIndex(startIndex);
        attrBO.setNameLike(dto.getAttrName());
        List<AttrEntity> selectList = attrService.selectList(attrBO);
        // 4.返回值封装
        if (CollectionUtils.isEmpty(selectList)){
            return ResponseEntity.success(returnPage);
        }
        // 5.查询属性值信息
        final List<Long> attrIdList = selectList.stream().map(AttrEntity::getAttrId).collect(Collectors.toList());
        List<AttrValueEntity> valueEntityList = attrService.selectAttrValueList(attrIdList);
        List<AttrInfoVO> returnList = new ArrayList<>();
        final Map<Long, List<AttrValueEntity>> valueListMap = valueEntityList.stream().collect(Collectors.groupingBy(AttrValueEntity::getAttrId));
        for (AttrEntity attrEntity : selectList) {
            final AttrInfoVO attrInfoVO = new AttrInfoVO();
            attrInfoVO.setAttrId(attrInfoVO.getAttrId());
            attrInfoVO.setAttrDesc(attrInfoVO.getAttrDesc());
            attrInfoVO.setAttrName(attrInfoVO.getAttrName());
            List<AttrInfoVO.AttrValueVO> valList = new ArrayList<>();
            final List<AttrValueEntity> valEntityList = valueListMap.get(attrEntity.getAttrId());
            if (CollectionUtils.isEmpty(valEntityList)){
                continue;
            }
            valEntityList.forEach(t->{
                final AttrInfoVO.AttrValueVO attrValueVO = new AttrInfoVO.AttrValueVO();
                attrValueVO.setAttrValue(t.getValue());
                attrValueVO.setAttrValueId(t.getAttrValueId());
                valList.add(attrValueVO);
            });
            attrInfoVO.setAttrValueList(valList);
            returnList.add(attrInfoVO);
        }
        return ResponseEntity.success(new PageUtil<>(dto.getPageSize(), dto.getPageNum(), selectCount, returnList));
    }

    @Override
    @ApiDoc(value = "新属性接口")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity<InsertAttrVO> insertAttr(InsertAttrDTO dto) throws BizWrapException {
        // 1.check request
        ValidationUtils.getInstance().validate(dto);
        // 2.check name
        LambdaQueryWrapper<AttrEntity> queryAttrWrapper = new LambdaQueryWrapper<>();
        queryAttrWrapper.eq(AttrEntity::getName,dto.getAttrName());
        Integer selectCount = attrService.selectCount(queryAttrWrapper);
        if (selectCount >0){
            throw ExceptionWrap.wrap(GoodsCodeEnum.ATTR_INFO_EXIST_ERROR);
        }
        // 3.builder attr entity
        AttrEntity attrEntity = new AttrEntity();
        attrEntity.setAttrType(dto.getAttrType());
        attrEntity.setName(dto.getAttrName());
        attrEntity.setDesc(dto.getAttrDesc());
        attrEntity.setUpdateTime(new Date());
        attrEntity.setCreateTime(new Date());
        attrService.insert(attrEntity);
        // 4.builder attr value
        List<AttrValueEntity> valueEntityList = this.getAttrValueEntities(dto.getAttrValueList(), attrEntity);
        attrService.batchInsertAttrVal(valueEntityList);
        // 5.return obj
        return ResponseEntity.success(new InsertAttrVO(attrEntity.getAttrId()));
    }

    private  List<AttrValueEntity> getAttrValueEntities( List<String> attrValueList, AttrEntity attrEntity) {
        List<AttrValueEntity> valueEntityList = new ArrayList<>();
        attrValueList.forEach(t->{
            AttrValueEntity attrValueEntity = new AttrValueEntity();
            attrValueEntity.setAttrId(attrEntity.getAttrId());
            attrValueEntity.setValue(t);
            attrValueEntity.setCreateTime(new Date());
            attrValueEntity.setUpdateTime(new Date());
            valueEntityList.add(attrValueEntity);
        });
        return valueEntityList;
    }

    @Override
    @ApiDoc(value = "修改属性接口")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity<Void> modifyAttr(ModifyAttrDTO dto) throws BizWrapException {
        // 1.check request
        ValidationUtils.getInstance().validate(dto);
        // 2.check name
        LambdaQueryWrapper<AttrEntity> queryAttrWrapper = new LambdaQueryWrapper<>();
        queryAttrWrapper.eq(AttrEntity::getName,dto.getAttrName());
        queryAttrWrapper.ne(AttrEntity::getAttrId,dto.getAttrId());
        Integer selectCount = attrService.selectCount(queryAttrWrapper);
        if (selectCount >0){
            throw ExceptionWrap.wrap(GoodsCodeEnum.ATTR_NAME_EXIST_ERROR);
        }
        // 3.check attr
        AttrEntity attrEntity = attrService.selectById(dto.getAttrId());
        if (ObjectUtils.isEmpty(attrEntity)){
            throw ExceptionWrap.wrap(GoodsCodeEnum.ATTR_INFO_NOT_EXIST_ERROR);
        }
        // 4.builder model
        List<String> attrValueList = dto.getAttrValueList();
        if (CollectionUtils.isEmpty(attrValueList)){
            return ResponseEntity.success();
        }
        attrService.deleteAttrValue(attrEntity.getAttrId());
        List<AttrValueEntity> valueEntityList = this.getAttrValueEntities(dto.getAttrValueList(), attrEntity);
        attrService.batchInsertAttrVal(valueEntityList);
        return ResponseEntity.success();
    }

    @Override
    @ApiDoc(value = "删除属性接口")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity<Void> delAttr(DeleteAttrDTO dto) throws BizWrapException {
        // 1.check request
        ValidationUtils.getInstance().validate(dto);
        // 2.query info
        AttrEntity attrEntity = attrService.selectById(dto.getAttrId());
        if (ObjectUtils.isEmpty(attrEntity)){
            return ResponseEntity.success();
        }
        // 3.del attr
        attrService.deleteAttrById(dto.getAttrId());
        // 4.del attr value
        attrService.deleteAttrValue(dto.getAttrId());
        // 5.del category attr
        categoryService.deleteAttrByAttrId(dto.getAttrId());
        // 6.del sku attr
        // 7.del spu attr
        return ResponseEntity.success();
    }
}
